import time
from datetime import datetime
from time import sleep
from selenium.webdriver.support.select import Select
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as ec
from test_tools.logger import Logger
from test_tools.class_mysql import Conn
from selenium.webdriver.common.action_chains import ActionChains as ac


class BasePage:

    def __init__(self, driver):
        self.driver = driver
        self.logger = Logger()
        self.conn = Conn("root", "diama_239", "192.168.1.239", "iconductor_media")

    def get_ele(self, locator: tuple, file_name):
        """
        元素定位标签
        :param locator:定位方式（元组类型）
        :param file_name: 定位失败，截图保存
        :return: 定位不到的元素标签，如果定位失败，返回None
        """
        # 定位前,先进行显示等待操作
        self.logger.info(f"开始等待{str(locator)}元素")
        self.wait(locator)
        try:
            ele = self.driver.find_element(*locator)
        except Exception as e:
            # 定位失败，截图保存
            self.get_screen_shot(file_name)
            ele = None
            self.logger.error("元素%s定位失败" % str(locator))
        return ele

    def get_code(self, locator: tuple, file_name, attribute):
        """
        获取登录验证码
        :param locator: 验证码元素定位方式
        :param file_name: 定位失败文件名
        :param attribute: 验证码元素的src属性
        :return: 验证码
        """
        src = self.get_attribute(locator, file_name, attribute)
        uuid = src[src.find('=')+1:]
        sql = f"SELECT code FROM sys_captcha WHERE uuid = '{uuid}';"
        data = self.execute_mysql(sql, 'one')
        code = data['code']
        return code

    def wait(self, locator: tuple, time=20, poll =1):
        """
        显示等待
        :param locator:需要等待的元素标签定位方式
        :param time:最长等待时间
        :param poll:轮询间隔时间
        :return:
        """
        self.logger.info("开始等待%s元素"%str(locator))
        try:
            start = datetime.now()
            WebDriverWait(self.driver, time, poll).until(ec.visibility_of_element_located(locator))
            end = datetime.now()
            times = (end-start).seconds
            self.logger.info("元素%s等待成功, 耗时%d秒" % (str(locator), times))
        except Exception as e:
            self.logger.error("元素%s等待失败,请确认" % str(locator))
            return None

    def get_screen_shot(self, file_name):
            """
            截图操作
            :param self:图片的名称（不包含图片保存路径及图片后缀）  名称格式为：页面名_功能名_操作名
            :return:
            """
            path = './test_results/imgs/'+file_name+'.png'
            self.driver.get_screenshot_as_file(path)
            self.logger.info("截图操作完成!")

    def click(self, locator, file_name):
        """
        点击操作
        :param locator:元素定位方式（元组类型）
        :param file_name:
        :return:
        """
        ele = self.get_ele(locator, file_name)
        if ele is not None or ele != "":
            sleep(0.5)
            ele.click()
            # js = "arguments[0].click();"
            # self.execute_js(js, ele)
            self.logger.info("元素%s点击操作成功!" % str(locator))
            return

    def clear(self, locator, file_name):
        """
        清空输入框
        :param locator:
        :param file_name:
        :return:
        """
        ele = self.get_ele(locator, file_name)
        ele.clear()

    def input(self, locator, value, file_name):
        """
        输入操作
        :param locator:元素定位方式（元组类型）
        :param value:
        :param file_name:
        :return:
        """
        ele = self.get_ele(locator, file_name)
        # sleep(1)
        # ele.clear()
        # sleep(1)
        if ele is not None or ele !="":
            ele.send_keys(value)
            self.logger.info("元素%s输入操作成功!" % str(locator))

    def upload_file(self, locator: tuple, path, file_name):
        """
        上传文件
        :param locator:元素定位方式（元组类型）
        :param path: 绝对路径地址
        :param file_name:
        :return:
        """
        try:
            ele = self.driver.find_element(*locator)
            if ele is not None or ele != "":
                try:
                    ele.send_keys(path)
                    self.logger.info("文件%s上传成功!" % str(path))
                except Exception as e:
                    self.logger.error("文件%s上传失败,请确认!" % str(path))
        except Exception as e:
            self.logger.error("input标签定位失败, 请确认!")

    def switch_window(self, index=-1):
        """
        浏览器窗口切换
        :param index:
        :return:
        """
        handles = self.driver.window_handles
        self.driver.switch_to.window(handles[index])
        sleep(1)
        self.logger.info('窗口切换操作完成!')

    def switch_into_frame(self, locator, file_name):
        """
        切入frame
        :param locator:
        :param file_name:
        :return:
        """
        ele = self.get_ele(locator, file_name)
        if ele is not None or ele != "":
            self.driver.switch_to.frame(ele)
            self.logger.info("切入frame%s成功" % str(locator))

    def switch_out_frame(self):
        self.driver.switch_to.default_content()
        self.logger.info('frame切出操作成功!')

    def switch_alert(self, type='a', value=None):
        """
        切换alert
        :param type:
        :param value:
        :return:
        """
        if type == "a":
            self.driver.switch_to.alert.accept()
        elif type == "d":
            self.driver.switch_to.alert.dismiss()
        elif type == "s":
            self.driver.switch_to.alert.send_keys(value)
            self.driver.switch_to.alert.accept()
        else:
            self.logger.warning('无效操作，请确认！')

    def select(self, locator, file_name, visible_text):
        """
        下拉框操作
        :param locator:
        :param file_name:
        :param visible_text:选择的显示文本值
        :return:
        """
        ele = self.get_ele(locator, file_name)
        if ele is not None or ele != "":
            select = Select(ele)
            select.select_by_visible_text(visible_text)
            self.logger.info('下拉框选择操作成功')

    def execute_js(self, js, ele=None):
        """
        执行js脚本
        :param js:
        :param ele:
        :return:
        """
        self.driver.execute_script(js, ele)
        self.logger.info("js操作成功！")

    def execute_mysql(self, sql='', num='all'):
        """执行sql语句"""
        try:
            datas = self.conn.execute(sql, num)
            return datas
        except Exception as e:
            self.logger.error('sql执行失败!')

    def remove_attribute(self, locator, file_name, attribute):
        """
        移除指定元素的属性
        :param locator:
        :param file_name:
        :param attribute: 需要移除的属性名
        :return:
        """
        ele = self.get_ele(locator, file_name)
        if ele is not None or ele != "":
            js = "arguments[0].removeAttribute('%s')"%attribute
            self.execute_js(js, ele)
            self.logger.info("成功移除元素%s属性" % str(locator))

    def get_text(self, locator, file_name):
        """
        获取指定元素标签的指定属性值
        :param locator:
        :param file_name:
        :return:
        """
        ele = self.get_ele(locator, file_name)
        if ele is not None or ele != "":
            text = ele.text
            return text

    def get_attribute(self, locator, file_name, attribute):
        """
        获取指定元素标签的指定属性的值
        :param locator:
        :param file_name:
        :param attribute:
        :return:
        """
        ele = self.get_ele(locator, file_name)
        if ele is not None or ele != "":
            return ele.get_attribute(attribute)

    def suspension_loc(self, locator1, locator2, file_name):
        """
        悬浮定位元素
        :param locator1: 悬浮框定位方式
        :param locator2: 悬浮框中元素定位方式
        :param file_name: 定位失败截图名
        :return:
        """
        sleep(1)
        ele1 = self.get_ele(locator1, file_name)  # 悬浮框定位
        if ele1 is not None or ele1 != "":
            ac(self.driver).move_to_element(ele1).perform()  # 鼠标悬浮
            sleep(1)
            ele2 = self.get_ele(locator2, file_name).click()
            sleep(1)
            return ele2

    def move_mouse_slowly(self):
        """
        控制浏览器滚动条缓慢下拉到最低
        :return:
        """
        # 获取当前窗口高度
        js = "return action=document.body.scrollHeight"
        # 初始化现在滚动条所在高度为0
        height = 0
        # 当前窗口总高度
        new_height = self.driver.execute_script(js)

        while height < new_height:
            # 将滚动条调整至页面底部
            for i in range(height, new_height, 100):
                self.driver.execute_script('window.scrollTo(0, {})'.format(i))
                time.sleep(0.2)
            height = new_height
            time.sleep(1)
            new_height = self.driver.execute_script(js)

    def back(self):
        self.driver.back()

    def forward(self):
        self.driver.forward()

    def refresh(self):
        self.driver.refresh()

    def close(self):
        self.driver.close()

